/*
 * Sync.h
 *
 *  Created on: 2011-7-7
 *      Author: gexiao
 */
/*
 * Object synchronization functions.
 */
#ifndef SYNC_H_
#define SYNC_H_

/*
 * Monitor shape field.  Used to distinguish immediate thin locks from
 * indirecting fat locks.
 */
#define LW_SHAPE_THIN 0
#define LW_SHAPE_FAT 1
#define LW_SHAPE_MASK 0x1
#define LW_SHAPE(x) ((x) & LW_SHAPE_MASK)

/*
 * Hash state field.  Used to signify that an object has had its
 * identity hash code exposed or relocated.
 */
#define LW_HASH_STATE_UNHASHED 0
#define LW_HASH_STATE_HASHED 1
#define LW_HASH_STATE_HASHED_AND_MOVED 3
#define LW_HASH_STATE_MASK 0x3
#define LW_HASH_STATE_SHIFT 1
#define LW_HASH_STATE(x) (((x) >> LW_HASH_STATE_SHIFT) & LW_HASH_STATE_MASK)

/*
 * Monitor accessor.  Extracts a monitor structure pointer from a fat
 * lock.  Performs no error checking.
 */
#define LW_MONITOR(x) \
  ((Monitor*)((x) & ~((LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT) | \
                      LW_SHAPE_MASK)))

/*
 * Lock owner field.  Contains the thread id of the thread currently
 * holding the lock.
 */
#define LW_LOCK_OWNER_MASK 0xffff
#define LW_LOCK_OWNER_SHIFT 3
#define LW_LOCK_OWNER(x) (((x) >> LW_LOCK_OWNER_SHIFT) & LW_LOCK_OWNER_MASK)

/*
 * Lock recursion count field.  Contains a count of the numer of times
 * a lock has been recursively acquired.
 */
#define LW_LOCK_COUNT_MASK 0x1fff
#define LW_LOCK_COUNT_SHIFT 19
#define LW_LOCK_COUNT(x) (((x) >> LW_LOCK_COUNT_SHIFT) & LW_LOCK_COUNT_MASK)

struct Object;
struct Monitor;
struct Thread;
typedef struct Monitor Monitor;

#define QUIET_ZYGOTE_MONITOR 1

/*
 * Initialize a Lock to the proper starting value.
 * This is necessary for thin locking.
 */
#define DVM_LOCK_INITIAL_THIN_VALUE (0)

#define DVM_LOCK_INIT(lock) \
    do { *(lock) = DVM_LOCK_INITIAL_THIN_VALUE; } while (0)

/*
 * Returns true if the lock has been fattened.
 */
#define IS_LOCK_FAT(lock)   (LW_SHAPE(*(lock)) == LW_SHAPE_FAT)

/*
 * Acquire the object's monitor.
 */
void dvmLockObject(struct Thread* self, struct Object* obj);

/* Returns true if the unlock succeeded.
 * If the unlock failed, an exception will be pending.
 */
bool dvmUnlockObject(struct Thread* self, struct Object* obj);

/*
 * Implementations of some java/lang/Object calls.
 */
void dvmObjectWait(struct Thread* self, struct Object* obj, s8 timeout,
		s4 nanos, bool interruptShouldThrow);
void dvmObjectNotify(struct Thread* self, struct Object* obj);
void dvmObjectNotifyAll(struct Thread* self, struct Object* obj);

/*
 * Implementation of System.identityHashCode().
 */
u4 dvmIdentityHashCode(struct Object* obj);

/*
 * Implementation of Thread.sleep().
 */
void dvmThreadSleep(u8 msec, u4 nsec);

/*
 * Implementation of Thread.interrupt().
 *
 * Interrupt a thread.  If it's waiting on a monitor, wake it up.
 */
void dvmThreadInterrupt(struct Thread* thread);

//create a new monitor struct
Monitor* dvmCreateMonitor(struct Object* obj);

/*
 * Frees unmarked monitors from the monitor list.  The given callback
 * routine should return a non-zero value when passed a pointer to an
 * unmarked object.
 */
void dvmSweepMonitorList(Monitor** mon, int(*isUnmarkedObject)(void*));

/* free monitor list */
void dvmFreeMonitorList(void);

/*
 * Get the object a monitor is part of.
 *
 * Returns NULL if "mon" is NULL or the monitor is not part of an object
 * (which should only happen for Thread.sleep() in the current implementation).
 */
struct Object* dvmGetMonitorObject(Monitor* mon);
/*
 * Get the thread that holds the lock on the specified object.  The
 * object may be unlocked, thin-locked, or fat-locked.
 *
 * The caller must lock the thread list before calling here.
 */
struct Thread* dvmGetObjectLockHolder(struct Object* obj);
/*
 * Checks whether the object is held by the specified thread.
 */
bool dvmHoldsLock(struct Thread* thread, struct Object* obj);
/*
 * Relative timed wait on condition
 */
int dvmRelativeCondWait(pthread_cond_t* cond, pthread_mutex_t* mutex,
                         s8 msec, s4 nsec);

/*
 * Debug.
 */
void dvmDumpMonitorInfo(const char* msg);

#endif /* SYNC_H_ */
